home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / DEMON / RISCOS2 / TCP_131S.ARC / c / NRS < prev    next >
Text File  |  1994-03-03  |  10KB  |  275 lines

  1. /* This module implements the serial line framing method used by
  2.  * net/rom nodes.  This allows the net/rom software to talk to
  3.  * an actual net/rom over its serial interface, which is useful
  4.  * if we want to do packet switching for multi-line wormholes.
  5.  * Dan Frank, W9NK
  6.  */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <time.h>
  11. #include "global.h"
  12. #include "mbuf.h"
  13. #include "iface.h"
  14. #include "ax25.h"
  15. #include "nrs.h"
  16. #include "asy.h"
  17. #include "trace.h"
  18. #include "arc.h"
  19. #include "misc.h"
  20.  
  21. static int  nrsq(int16, struct mbuf *);
  22. static void nrasy_start(int16);
  23. static struct mbuf *nrs_encode(struct mbuf *);
  24. static struct mbuf *nrs_decode(int16, char);
  25.  
  26. /* control structures, sort of overlayed on async control blocks */
  27. struct nrs nrs[ASY_MAX];
  28.  
  29. /* Send a raw net/rom serial frame */
  30. int nrs_raw(struct interface *interface, struct mbuf *bp)
  31. {
  32.         dump(interface,IF_TRACE_OUT,TRACE_AX25,bp) ;
  33.         
  34.         /* Queue a frame on the output queue and start transmitter */
  35.         return(nrsq(interface->dev,bp));
  36. }
  37.  
  38. /* Encode a raw packet in net/rom framing, put on link output queue, and kick
  39.  * transmitter
  40.  */
  41. static int nrsq(int16 dev, struct mbuf *bp)
  42. /* Buffer to be sent */
  43. {
  44.         register struct nrs *sp;
  45.  
  46.         if((bp = nrs_encode(bp)) == NULLBUF)
  47.                 return -1; 
  48.  
  49.         sp = &nrs[dev];
  50.         enqueue(&sp->sndq,bp);
  51.         sp->sndcnt++;
  52.         if(sp->tbp == NULLBUF)
  53.                 nrasy_start(dev);
  54.         return 0;
  55. }
  56.  
  57. /* Start output, if possible, on asynch device dev */
  58. static void nrasy_start(int16 dev)
  59. {
  60.         register struct nrs *sp;
  61.         static int  asy_failed = 0;
  62.         static char *asy_buffer;
  63.         static int  asy_length;
  64.         char *temp_buffer;
  65.         int  temp_length;
  66.         int n;
  67.  
  68.         if (!asy_failed) {
  69.                 sp = &nrs[dev];
  70.                 if(sp->tbp != NULLBUF){
  71.                         /* transmission just completed */
  72.                         free_p(sp->tbp);
  73.                         sp->tbp = NULLBUF;
  74.                 }
  75.                 if(sp->sndq == NULLBUF)
  76.                        return; /* No work */
  77.  
  78.                 sp->tbp = dequeue(&sp->sndq);
  79.                 sp->sndcnt--;
  80.                 if ((n = asy_output(dev,sp->tbp->data,sp->tbp->cnt)) < sp->tbp->cnt) {
  81.                        asy_failed = 1;
  82.                        asy_length = sp->tbp->cnt - n;
  83.                        asy_buffer = malloc(asy_length);
  84.                        memcpy(asy_buffer,sp->tbp->data+n,asy_length);
  85.                 }
  86.         }
  87.         else {
  88.                 if ((n = asy_output(dev,asy_buffer,asy_length)) < asy_length) {
  89.                        temp_length = asy_length - n;
  90.                        temp_buffer = malloc(temp_length);
  91.                        memcpy(temp_buffer,asy_buffer+n,temp_length);
  92.                        free(asy_buffer);
  93.                        asy_length = temp_length;
  94.                        asy_buffer = temp_buffer;
  95.                 }
  96.                 else {
  97.                        asy_failed = 0;
  98.                        free(asy_buffer);
  99.                 }
  100.         }
  101. }
  102.  
  103. /* Encode a packet in net/rom serial format */
  104. static struct mbuf *nrs_encode(struct mbuf *bp)
  105. {
  106.         struct mbuf *lbp;       /* Mbuf containing line-ready packet */
  107.         register char *cp;
  108.         char c;
  109.         unsigned char csum = 0 ;
  110.  
  111.         /* Allocate output mbuf that's twice as long as the packet.
  112.          * This is a worst-case guess (consider a packet full of STX's!)
  113.          * Add five bytes for STX, ETX, checksum, and two nulls.
  114.          */
  115.         lbp = alloc_mbuf(2*len_mbuf(bp) + 5);
  116.         if(lbp == NULLBUF){
  117.                 /* No space; drop */
  118.                 free_p(bp);
  119.                 return NULLBUF;
  120.         }
  121.         cp = lbp->data;
  122.  
  123.         *cp++ = STX ;
  124.  
  125.         /* Copy input to output, escaping special characters */
  126.         while(pullone(&bp,&c) == 1){
  127.                 switch(uchar(c)){
  128.                 case STX:
  129.                 case ETX:
  130.                 case DLE:
  131.                         *cp++ = DLE;
  132.                         /* notice drop through to default */
  133.                 default:
  134.                         *cp++ = c;
  135.                 }
  136.                 csum += uchar(c) ;
  137.         }
  138.         *cp++ = ETX;
  139.         *cp++ = csum ;
  140.         *cp++ = NUL ;
  141.         *cp++ = NUL ;
  142.         
  143.         lbp->cnt = cp - lbp->data;
  144.         return lbp;
  145. }
  146. /* Process incoming bytes in net/rom serial format
  147.  * When a buffer is complete, return it; otherwise NULLBUF
  148.  */
  149. static struct mbuf *nrs_decode(int16 dev, char c)
  150. /* Incoming character */
  151. {
  152.         struct mbuf *bp;
  153.         register struct nrs *sp;
  154.  
  155.         sp = &nrs[dev];
  156.         switch(sp->state) {
  157.                 case NRS_INTER:
  158.                         if (uchar(c) == STX) {  /* look for start of frame */
  159.                                 sp->state = NRS_INPACK ;        /* we're in a packet */
  160.                                 sp->csum = 0 ;                          /* reset checksum */
  161.                         }
  162.                         return NULLBUF ;
  163.                         break ; /* just for yucks */
  164.                 case NRS_CSUM:
  165.                         bp = sp->rbp ;
  166.                         sp->rbp = NULLBUF ;
  167.                         sp->rcnt = 0 ;
  168.                         sp->state = NRS_INTER ; /* go back to inter-packet state */
  169.                         if (sp->csum == uchar(c)) {
  170.                                 sp->packets++ ;
  171.                                 return bp ;
  172.                         }
  173.                         else {
  174.                                 free_p(bp) ;    /* drop packet with bad checksum */
  175.                                 sp->errors++ ;  /* increment error count */
  176.                                 return NULLBUF ;
  177.                         }
  178.                         break ;
  179.                 case NRS_ESCAPE:
  180.                         sp->state = NRS_INPACK ;        /* end of escape */
  181.                         break ;                 /* this will drop through to char processing */
  182.                 case NRS_INPACK:
  183.                         switch (uchar(c)) {
  184.                                 /* If we see an STX in a packet, assume that previous */
  185.                                 /* packet was trashed, and start a new packet */
  186.                                 case STX:
  187.                                         free_p(sp->rbp) ;
  188.                                         sp->rbp = NULLBUF ;
  189.                                         sp->rcnt = 0 ;
  190.                                         sp->csum = 0 ;
  191.                                         sp->errors++ ;
  192.                                         return NULLBUF ;
  193.                                         break ;
  194.                                 case ETX:
  195.                                         sp->state = NRS_CSUM ;  /* look for checksum */
  196.                                         return NULLBUF ;
  197.                                         break ;
  198.                                 case DLE:
  199.                                         sp->state = NRS_ESCAPE ;
  200.                                         return NULLBUF ;
  201.                                         break ;
  202.                         }
  203.         }
  204.         /* If we get to here, it's with a character that's part of the packet.
  205.          * Make sure there's space for it.
  206.          */
  207.         if(sp->rbp == NULLBUF){
  208.                 /* Allocate first mbuf for new packet */
  209.                 if((sp->rbp1 = sp->rbp = alloc_mbuf(NRS_ALLOC)) == NULLBUF) {
  210.                         sp->state = NRS_INTER ;
  211.                         return NULLBUF; /* No memory, drop */
  212.                 }
  213.                 sp->rcp = sp->rbp->data;
  214.         } else if(sp->rbp1->cnt == NRS_ALLOC){
  215.                 /* Current mbuf is full; link in another */
  216.                 if((sp->rbp1->next = alloc_mbuf(NRS_ALLOC)) == NULLBUF){
  217.                         /* No memory, drop whole thing */
  218.                         free_p(sp->rbp);
  219.                         sp->rbp = NULLBUF;
  220.                         sp->rcnt = 0;
  221.                         sp->state = NRS_INTER ;
  222.                         return NULLBUF;
  223.                 }
  224.                 sp->rbp1 = sp->rbp1->next;
  225.                 sp->rcp = sp->rbp1->data;
  226.         }
  227.         /* Store the character, increment fragment and total
  228.          * byte counts
  229.          */
  230.         *sp->rcp++ = c;
  231.         sp->rbp1->cnt++;
  232.         sp->rcnt++;
  233.         sp->csum += uchar(c) ;  /* add to checksum */
  234.         return NULLBUF;
  235. }
  236.  
  237. /* Process net/rom serial line I/O */
  238. void nrs_recv(struct interface *interface)
  239. {
  240.         char c;
  241.         struct mbuf *bp;
  242.         int16 dev;
  243.  
  244.         dev = interface->dev;
  245.         /* Process any pending input */
  246.         while(asy_recv(dev,&c,1) != 0)
  247.                 if((bp = nrs_decode(dev,c)) != NULLBUF) {
  248.                         dump(interface,IF_TRACE_IN,TRACE_AX25,bp) ;
  249.                         ax_recv(interface,bp);
  250.                 }
  251.  
  252.         /* Kick the transmitter if it's idle */
  253.         nrasy_start(dev);
  254. }
  255.  
  256. /* donrstat:  display status of active net/rom serial interfaces */
  257. int donrstat(int argc, char **argv)
  258. {
  259.         register struct nrs *np ;
  260.         register int i ;
  261.  
  262.         argc = argc;
  263.         argv = argv;
  264.  
  265.         cwprintf(NULL, "Interface  SndQ  RcvB  NumReceived  CSumErrors\r\n") ;
  266.  
  267.         for (i = 0, np = nrs ; i < ASY_MAX ; i++, np++)
  268.                 if (np->iface != NULLIF)
  269.                         cwprintf(NULL, " %8s   %3d  %4d   %10lu  %10lu\r\n",
  270.                                         np->iface->name, np->sndcnt, np->rcnt,
  271.                                         np->packets, np->errors) ;
  272.  
  273.         return 0 ;
  274. }
  275.